package com.msg.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.msg.core.enums.FileExceptionEnum;
import com.msg.core.exception.ProjectException;
import com.msg.core.result.Result;
import com.msg.domain.model.SysFile;
import com.msg.service.SysFileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.dromara.x.file.storage.core.platform.MultipartUploadSupportInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;

@RequiredArgsConstructor
@RestController
@Slf4j
@RequestMapping("/file")
public class FileController {

    private final FileStorageService fileStorageService;
    private final SysFileService sysFileService;
    /**
     * 文件上传，临时文件，默认保存30天
     *
     * platform:存储平台
     * @return
     */
    @PostMapping("/upload")
    public Result<?> upload(@RequestParam(value = "file") MultipartFile file,
                            @RequestParam(value = "platform",required = false) String platform){
        String path= DateUtil.format(new Date(),"yyyyMMdd")+"/";
        FileInfo fileInfo=fileStorageService.of(file)
                .setPlatform(StrUtil.isNotBlank(platform),platform)
                .setPath(path)
                .upload();
        return Result.success(fileInfo);
    }


    /**
     * 文件上传 临时文件，默认保存30天
     * 不需要鉴权
     *
     * platform:存储平台
     * @return
     */
    @PostMapping("/upload-open")
    public Result<?> uploadOpen(@RequestParam(value = "file") MultipartFile file,
                                @RequestParam(value = "platform",required = false) String platform){
        String path= DateUtil.format(new Date(),"yyyyMMdd")+"/";
        FileInfo fileInfo=fileStorageService.of(file)
                .setPlatform(StrUtil.isNotBlank(platform),platform)
                .setPath(path)
                .upload();
        return Result.success(fileInfo);
    }

    /**
     * 分片上传文件 临时文件，默认保存30天
     * 适合大文件上传
     *
     * part:分片的编号
     * total：总共的分片数目
     * platform:存储平台
     * fileId：文件id，一次任务，共享一个
     *
     * @return
     */
    @PostMapping("/upload-part")
    public Result<?> uploadPart(@RequestParam(value = "file") MultipartFile file,
                                @RequestParam(value = "part") Integer part,
                                @RequestParam(value = "total") Integer total,
                                @RequestParam(value = "fileId",required = false) Long fileId,
                                @RequestParam(value = "platform",required = false) String platform
                                ){
        MultipartUploadSupportInfo supportInfo =fileStorageService.isSupportMultipartUpload();
        if(!supportInfo.getIsSupport()){
            log.info("当前的存储平台不支持分片上传");
        }
        if(part>1 && fileId==null){
            throw new ProjectException(FileExceptionEnum.FILEID_BLANK);
        }
        FileInfo fileInfo;
        if(fileId!=null){
            fileInfo=sysFileService.getByFileId(fileId);
        }else{
            //初始化
            String path= DateUtil.format(new Date(),"yyyyMMdd")+"/";
            fileInfo = fileStorageService.initiateMultipartUpload()
                    .setOriginalFilename(file.getOriginalFilename())
                    .setPlatform(StrUtil.isNotBlank(platform),platform)
                    .setPath(path)
                    .init();
        }
        fileStorageService.uploadPart(fileInfo,part,file).upload();
        if(part.equals(total)){
            fileStorageService.completeMultipartUpload(fileInfo).complete();
        }
        return Result.success(fileInfo);
    }

    /**
     * 图片上传 临时文件，默认保存30天
     *
     * platform:存储平台
     * thumWidth:缩略图宽度
     * thumHeight:缩略图高度
     */
    @PostMapping("/upload-image")
    public Result<?> uploadImage(@RequestParam(value = "file") MultipartFile file,
                                 @RequestParam(value = "platform",required = false) String platform,
                                 @RequestParam(value = "thumWidth",required = false) Integer thumWidth,
                                 @RequestParam(value = "thumHeight",required = false) Integer thumHeight
                                 ) {

        //默认缩略图的长度是200*200
        if(thumWidth==null){
            thumWidth=200;
        }
        if(thumHeight==null){
            thumHeight=200;
        }
        String path="img/"+DateUtil.format(new Date(),"yyyyMMdd")+"/";
        FileInfo fileInfo=fileStorageService.of(file)
                .setPath(path)
                .setPlatform(StrUtil.isNotBlank(platform),platform)
                .thumbnail(thumWidth,thumHeight)
                .upload();
        return Result.success(fileInfo);
    }

    /**
     * 获取文件信息
     * @return
     */
    @GetMapping("/fileInfo")
    public Result<?> getFileInfo(String fileIdOrUrl){
        SysFile sysFile=null;
        if(StrUtil.isNotBlank(fileIdOrUrl)){
            sysFile=sysFileService.getOne(new LambdaQueryWrapper<SysFile>()
                    .or(wrapper -> wrapper.eq(SysFile::getId, fileIdOrUrl))
                    .or(wrapper -> wrapper.eq(SysFile::getUrl, fileIdOrUrl))
            );
        };
        return Result.success(sysFile);
    }

    /**
     * 获取文件列表
     * objectId :对用的表的主键
     * objectType: 对应表的字段，一般为 表名：字段名 示例：sys_user:img_code
     * @return
     */
    @GetMapping("/listFile")
    public List<SysFile> listFile(String objectId,String objectType){
        if(StrUtil.isBlank(objectId)){
            throw new ProjectException(FileExceptionEnum.OBJECTID_BLANK);
        }
        List<SysFile> fileList = sysFileService.list(new LambdaQueryWrapper<SysFile>()
                .eq(SysFile::getObjectId,objectId)
                .eq(StrUtil.isNotBlank(objectType),SysFile::getObjectType,objectType)
        );
        return fileList;
    }


    /**
     * 使用文件，文件会永久存储
     * @return
     */
    @PostMapping("/useFile")
//    public Result<?> useFile(@RequestBody @Valid List<FileUseDTO> list){
//        if(CollUtil.isNotEmpty(list)){
//            List<SysFile> files=new ArrayList<>();
//            list.forEach(item->{
//                String fileIdOrUrl= item.getFileIdOrUrl();
//                SysFile file=sysFileService.getOne(new LambdaQueryWrapper<SysFile>()
//                        .or(wrapper -> wrapper.eq(SysFile::getId, fileIdOrUrl))
//                        .or(wrapper -> wrapper.eq(SysFile::getUrl, fileIdOrUrl))
//                );
//                file.setObjectId(item.getObjectId());
//                file.setObjectType(item.getObjectType());
//                file.setFileStstus(FileStatusEnum.REAL.getCode());
//                files.add(file);
//            });
//            sysFileService.saveOrUpdateBatch(files);
//        }
//        return Result.success();
//    }


    /**
     * 下载文件
     */
    @GetMapping("/download")
    public Result<?> download(String url, HttpServletResponse response) throws Exception{

        FileInfo file=sysFileService.getByUrl(url);
        if (file!=null){
            response.setHeader("content-type","application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition","attchment;filename=" + java.net.URLEncoder.encode(file.getOriginalFilename(),"UTF-8"));

            byte[] bytes = fileStorageService.download(url)
                    .setProgressListener(((progressSize,allSize)->
                            System.out.println("已下载 " + progressSize + " 总大小" + allSize)
                     ))
                    .bytes();
            OutputStream out=response.getOutputStream();
            out.write(bytes);
            out.flush();
            out.close();
        }
        return Result.success();
    }

    /**
     * 删除文件
     * objectId  表id
     * objectType 表字段
     * 注意：
     *  如果不传objectType，会删除所有与objectId的相关数据，可能会删除多条
     */
    @GetMapping("/delete")
    public Result<?> delete(String objectId, String objectType) throws Exception{

        if(StrUtil.isBlank(objectId)){
            throw new ProjectException(FileExceptionEnum.OBJECTID_BLANK);
        }
        List<SysFile> fileList = sysFileService.list(new LambdaQueryWrapper<SysFile>()
                .eq(SysFile::getObjectId,objectId)
                .eq(StrUtil.isNotBlank(objectType),SysFile::getObjectType,objectType)
        );
        if(CollUtil.isNotEmpty(fileList)){
            fileList.forEach(item->{
                fileStorageService.delete(item.getUrl());
            });
        }
        return Result.success();
    }





}
